#ifndef UL_LIST_H
#define UL_LIST_H

#include "ul_config.h"

struct ul_list_node
{
    struct ul_list_node *next;                          /**< point to next node. */
    struct ul_list_node *prev;                          /**< point to prev node. */
};
typedef struct ul_list_node ul_list_t;                  /**< Type for lists. */

/**
 * @brief initialize a list
 *
 * @param l list to be initialized
 */
ul_inline void ul_list_init(ul_list_t *l)
{
    l->next = l->prev = l;
}

ul_inline void ul_list_remove(ul_list_t *n)
{
    n->next->prev = n->prev;
    n->prev->next = n->next;

    n->next = n->prev = n;
}

/**
 * @brief tests whether a list is empty
 * @param l the list to test.
 */
ul_inline int ul_list_isempty(const ul_list_t *l)
{
    return l->next == l;
}

/**
 * @brief insert a node after a list
 *
 * @param l list to insert it
 * @param n new node to be inserted
 */
ul_inline void ul_list_insert_after(ul_list_t *l, ul_list_t *n)
{
    l->next->prev = n;
    n->next = l->next;

    l->next = n;
    n->prev = l;
}

/**
 * @brief insert a node before a list
 *
 * @param n new node to be inserted
 * @param l list to insert it
 */
ul_inline void ul_list_insert_before(ul_list_t *l, ul_list_t *n)
{
    l->prev->next = n;
    n->prev = l->prev;

    l->prev = n;
    n->next = l;
}

/**
 * ul_list_for_each - iterate over a list
 * @pos:    the rt_list_t * to use as a loop cursor.
 * @head:   the head for your list.
 */
#define ul_list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)

/**
 * @brief get the struct for this entry
 * @param node the entry point
 * @param type the type of structure
 * @param member the name of list in structure
 */
#define ul_list_entry(node, type, member) \
    ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member)))

#endif
